package org.dragonnova.meetingclient.core.net;

import android.bluetooth.BluetoothDevice;
import android.content.Context;
import android.graphics.Bitmap;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.wifi.WifiInfo;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.text.SimpleDateFormat;
import java.util.Date;

/**
 *
 */
public final class SocketUtils {

	private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy年MM月dd日 HH时mm分");

	private static final char[] hexChars = {'0', '1', '2', '3', '4', '5',
			'6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};

	public static byte[] convertFileToBytes(File file) throws IOException {
		if (file != null && file.exists() && file.isFile()) {
			int size = (int) file.length();
			if (size == 0) {
				return new byte[0];
			}

			byte[] temp = new byte[size];
			int offset = 0;
			int readed;
			FileInputStream input = new FileInputStream(file);
			while (offset < size && (readed = input.read(temp, offset, size - offset)) != -1) {
				offset += readed;
			}

			if (offset != size) {
				throw new IOException("readed size error");
			}

			return temp;

		}else {
			throw new FileNotFoundException("File '" + file + "' does not exist");
		}
	}

	public static InputStream openRawResource(Context context, int resourceId) throws IOException {
		return context.getResources().openRawResource(resourceId);
	}

	public static InputStream openRawResource(Context context, int resourceId, long skipBytes) throws IOException {
		InputStream inputStream = context.getResources().openRawResource(resourceId);
		inputStream.skip(skipBytes);
		return inputStream;
	}

	public static byte[] convertFileToBytes(InputStream input) throws IOException {
		int size = (int) input.available();
		if (size == 0) {
			return new byte[0];
		}

		byte[] temp = new byte[size];
		int offset = 0;
		int readed;
		while (offset < size && (readed = input.read(temp, offset, size - offset)) != -1) {
			offset += readed;
		}

		if (offset != size) {
			throw new IOException("readed size error");
		}

		return temp;
	}

	public static boolean existWifiSsid(WifiInfo wifiInfo) {
		return wifiInfo != null && !wifiInfo.getSSID().equals("0x");
	}

	public static boolean getActiveNetworkInfo(NetworkInfo networkInfo) {
		return networkInfo != null && networkInfo.isConnected() && networkInfo.isAvailable();
	}

	public static boolean isMobileType(NetworkInfo networkInfo) {
		return networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_MOBILE;
	}

	public static boolean isWifiType(NetworkInfo networkInfo) {
		return networkInfo != null && networkInfo.getType() == ConnectivityManager.TYPE_WIFI;
	}

	public static boolean checkIP(String ip) {
		String[] ips = ip.split(":|\\.");
		if (ips != null && ips.length == 4) {
			try {
				return Integer.parseInt(ips[0]) > 0 && Integer.parseInt(ips[0]) < 255
						&& Integer.parseInt(ips[1]) > 0 && Integer.parseInt(ips[1]) <= 255
						&& Integer.parseInt(ips[2]) > 0 && Integer.parseInt(ips[2]) <= 255
						&& Integer.parseInt(ips[3]) > 0 && Integer.parseInt(ips[3]) <= 255;
			}catch (NumberFormatException e) {
				return false;
			}
		}
		return false;
	}

	public static String convertIntIpAddress(int ipAdress) {
		return (ipAdress & 0xFF ) + "." +
				((ipAdress >> 8 ) & 0xFF) + "." +
				((ipAdress >> 16 ) & 0xFF) + "." +
				( ipAdress >> 24 & 0xFF) ;
	}

	/**
	 * 返回当前时间
	 * @return
	 */
	public static String formatCurrentTime() {
		return dateFormat.format(new Date());
	}

	/**
	 *
	 *  Description: Mac地址转换字节数组
	 *  @author songxy  DateTime 2015年12月3日 上午11:28:30
	 *  @param macAddr
	 *  @return
	 */
	public static byte[] convertMacAddrToBytes(String macAddr) {
		String[] ips = macAddr.split(":|\\.");
		if (ips == null || ips.length != 6)
			throw new RuntimeException("Mac 格式出错"+macAddr);
		byte[] result = new byte[6];
		for (int i=0; i<result.length; i++) {
			result[i] = (byte) Integer.parseInt(ips[i], 16);
		}
		return result;
	}

	/**
	 * 字符串转字节数组
	 * @param ip
	 * @return
	 */
	public static byte[]  convertIpToBytes(String ip) {
		String[] ips = ip.split(":|\\.");
		if (ips == null || ips.length != 4)
			throw new RuntimeException("IP 格式出错"+ip);
		byte[] result = new byte[4];
		for (int i=0; i<result.length; i++) {
			result[i] = (byte) Integer.parseInt(ips[i]);
		}
		return result;
	}

	public static final void sendMsgByHandler(int MSG, Handler handler, Bundle bundle) {
		Message msg = handler.obtainMessage();
		msg.setData(bundle);
		handler.sendMessage(msg);
	}

	public static byte[] longToByte(long data, int length) {
		return intToByte((int) data, length);
	}

	public static byte[] intToByte(int data, int length) {
		byte[] result = new byte[length];
		byte[] temp = SocketUtils.int2byte(data);
		System.arraycopy(temp, 0, result, 0, result.length);
		return result;
	}

	/**
	 * 字节数组转字符串
	 *
	 * @param data
	 * @return
	 */
	public static String encodeHexStr(byte[] data) {
		return new String(encodeHex(data));
	}

	/**
	 * 字符串转字节数组
	 *
	 * @param data
	 * @return
	 */
	public static byte[] decodeHexStr(String data) {
		return decodeHex(data.toCharArray());
	}

	/**
	 * byte数组转int
	 *
	 * @param b
	 * @return
	 */
	public static int byte2Int(byte[] b) {
		if (b.length == 1) {
			return b[0] & 0xff;
		}else if (b.length == 2) {
			return ((b[0] & 0xff) << 8) | (b[1] & 0xff);
		}else if (b.length == 3) {
			return ((b[0] & 0xff) << 16) | ((b[1] & 0xff) << 8) | (b[2] & 0xff);
		}else if (b.length >= 4){
			ByteBuffer converter = ByteBuffer.wrap(b);
			converter.order(ByteOrder.nativeOrder());
			return converter.getInt();
		}else {
			throw new RuntimeException("byte length > 4 or < 1");
		}
	}


	/**
	 * 整型转字节
	 *
	 * @param i
	 * @return
	 */
	public static byte[] int2byte(int i) {
		byte[] b = new byte[4];
		for (int j = 0; j < 4; j++) {
			b[j] = (byte) (i >> (8 * j) & 0xff);
		}
		return b;
	}

	/**
	 * 二进制转换十六进制
	 *
	 * @param data
	 * @return
	 */
	public static String byte2HexString(byte[] data) {
		StringBuffer sb = new StringBuffer();
		if (data == null || data.length == 0) return null;
		for (int i = 0; i < data.length; i++) {
			sb.append("0x" + Integer.toHexString(data[i]));
		}
		return sb.toString();
	}

	/**
	 * 字节转16进制
	 *
	 * @param data
	 * @return
	 */
	public static String bytes2HexStr(byte[] data) {
		if (data == null) return null;
		else if (data.length > 0) {
			String result = new String();
			for (int i = 0; i < data.length; i++) {
				result += Integer.toHexString((int) data[i]);
			}
			return result;
		} else {
			return "";
		}
	}

	/**
	 * 解绑�?
	 *
	 * @param deviceClass
	 * @param device
	 * @return
	 * @throws Exception
	 */
	public static boolean removeBond(Class deviceClass, BluetoothDevice device) throws Exception {
		Method method = deviceClass.getMethod("removeBond");
		return (Boolean) method.invoke(device);
	}

	/**
	 * 绑定
	 *
	 * @param deviceClass
	 * @param device
	 * @return
	 * @throws Exception
	 */
	public static boolean createBond(Class deviceClass, BluetoothDevice device) throws Exception {
		Method method = deviceClass.getMethod("createBond");
		return (Boolean) method.invoke(device);
	}

	/**
	 * 解析蓝牙状�??
	 */
	public static String parseBluetoothDeviceState(int state) {
		return state == 12 ? "BOND_BONDED" :
				(state == 11 ? "BOND_BONDING" : "BOND_NONE");
	}

	private static char[] encodeHex(byte[] data) {
		char[] result = new char[data.length << 1];
		for (int i = 0, j = 0; i < data.length; i++) {
			result[j++] = hexChars[(data[i] & 0xF0) >>> 4];
			result[j++] = hexChars[(data[i] & 0x0F)];
		}
		return result;
	}

	public static byte[] Bitmap2Bytes(Bitmap bm) {
		ByteArrayOutputStream baos = new ByteArrayOutputStream();
		bm.compress(Bitmap.CompressFormat.JPEG, 100, baos);
		return baos.toByteArray();
	}

	private static byte[] decodeHex(char[] data) {
		byte[] result = new byte[data.length >> 1];
		for (int i = 0, j = 0; j < data.length; i++) {
			int temp = toDigit(data[j], j) << 4;
			j++;
			temp = temp | (toDigit(data[j], j));
			j++;
			result[i] = (byte) (temp & 0xff);
		}
		return result;
	}

	private static int toDigit(char ch, int idx) {
		int digit = Character.digit(ch, 16);
		if (digit == -1) {
			throw new RuntimeException("Illegal hexadecimal character " + ch + " at " + idx);
		}
		return digit;
	}
}
